package com.gmss.crawler.utils;

import cn.hutool.core.text.UnicodeUtil;
import org.apache.commons.lang3.StringUtils;

import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class CommonUtils {

    private static final char UNDERLINE = '_';

    private static final String IS_NOT_NUMBER = "^[1-9]\\d*|0$";

    // 经度
    private static final String LONGITUDE_MATCH = "[\\-+]?(0?\\d{1,2}|0?\\d{1,2}\\.\\d{4,15}|1[0-7]?\\d|1[0-7]?\\d\\.\\d{4,15}|180|180\\.0{4,15})";
    // 纬度
    private static final String LATITUDE_MATCH = "[\\-+]?([0-8]?\\d|[0-8]?\\d\\.\\d{4,15}|90|90\\.0{4,15})";
    // 数字或小数
    private static final String NUMBER = "^-?\\d+(\\.\\d+)?$";

    /**
     * json格式中，包含unicode编号
     *
     * @param result
     * @return
     */
    public static String jsonUnicodeToUtf8(String result) {
        return UnicodeUtil.toString(result);
        // hutool 4.1.17版本 unicode转utf8
//        return new JSONTokener(result).nextValue().toString();
    }


    //Unicode转中文方法
    private static String unicodeToCn(String unicode) {
        /** 以 \ u 分割，因为java注释也能识别unicode，因此中间加了一个空格*/
        String[] strs = unicode.split("\\\\u");
        String returnStr = "";
        // 由于unicode字符串以 \ u 开头，因此分割出的第一个字符是""。
        for (int i = 1; i < strs.length; i++) {
            returnStr += (char) Integer.valueOf(strs[i], 16).intValue();
        }
        return returnStr;
    }

    //中文转Unicode
    private static String cnToUnicode(String cn) {
        char[] chars = cn.toCharArray();
        String returnStr = "";
        for (int i = 0; i < chars.length; i++) {
            returnStr += "\\u" + Integer.toString(chars[i], 16);
        }
        return returnStr;
    }

    /**
     * 字符串首字母大写，比如idCard->IdCard
     *
     * @param
     */
    public static String initialsUpperCase(String s) {
        String str = null;
        if (s != null && s.length() > 0) {
            String[] split = s.split(" ");//按空格分隔成数组
            for (int i = 0; i < split.length; i++) {
                str = split[i].substring(0, 1).toUpperCase() + split[i].substring(1);
            }
        }
        return str;
    }

    /**
     * 把驼峰命名的字符转成下划线的方式，比如ip_address->ipAddress
     *
     * @param str
     * @return
     */
    public static String underline2camel(String str) {
        StringBuffer sb = new StringBuffer();

        if (str != null && str.length() > 0) {
            String[] arr = str.split("_");
            for (int i = 0; i < arr.length; i++) {
                String s = arr[i];
                if (s.length() > 0) {
                    // 首字母小写
                    if (i > 0) {
                        sb.append(s.substring(0, 1).toUpperCase());
                    } else {
                        sb.append(s.substring(0, 1));
                    }
                    sb.append(s.substring(1));
                }
            }

        }
        return sb.toString();
    }

    /**
     * 把驼峰命名的字符转成下划线的方式，比如ipAddress->ip_address
     *
     * @param str
     */
    public static String camel2underline(String str) {
        if (str == null) {
            return "";
        }
        int len = str.length();
        StringBuilder sb = new StringBuilder(len);
        for (int i = 0; i < len; i++) {
            char c = str.charAt(i);
            if (Character.isUpperCase(c)) {
                sb.append(UNDERLINE);
                sb.append(Character.toLowerCase(c));
            } else {
                sb.append(c);
            }
        }
        return sb.toString();
    }


    /**
     * 处理外国人姓名
     *
     * @param name 菲立普·希阿雷 Philippe G. Ciarlet
     * @return
     */
    public static String handleForeignName(String name) {
        String nameDian = "·";
        if (StringUtils.contains(name, nameDian)) {
            String foreignName = CommonUtils.replaceBlank(name);
            name = RegexUtils.replaceData(foreignName, RegexUtils.ENGLISH, "");
        }
        return name;
    }

    /***
     *
     * 验证中文名字
     * @param name
     * @return
     */
    public static boolean isChineseName(String name, int num) {
        if (name.contains("·")) {
            boolean a = true;
            String[] names = name.split("\\·");
            if (names.length == 1) {
                return false;
            }
            for (String n : names) {
                Pattern tpattern = Pattern.compile("^[\u4e00-\u9fa5]{" + n.length() + ",}$");
                Matcher matcher = tpattern.matcher(n);
                if (!matcher.find() || "".equals(n)) {
                    a = false;
                }
            }
            return a;
        }
        Pattern pattern = Pattern.compile("^[\u4e00-\u9fa5]{" + num + ",}$");
        Matcher matcher = pattern.matcher(name);
        if (matcher.find()) {
            return true;
        }
        return false;
    }


    /**
     * 验证手机号码
     *
     * @param mobiles
     * @return
     */
    public static boolean isMobile(String mobiles) {
        boolean flag = false;
        try {
            Pattern p = Pattern.compile("^((13[0-9])|(14[0-9])|(15[0-9])|(16[0-9])|(17[0-9])|(18[0-9]))\\d{8}$");
            Matcher m = p.matcher(mobiles);
            flag = m.matches();
        } catch (Exception e) {
            flag = false;
        }
        return flag;
    }

    /**
     * 点替换为空，验证是否为数字
     *
     * @param content
     * @return
     */
    public static boolean validateNum(String content) {
        if (content.contains(".")) {
            content = content.replaceAll("\\.", "");
        }

        Pattern p = Pattern.compile(IS_NOT_NUMBER);
        Matcher m = p.matcher(content);
        return m.matches();
    }

    /**
     * 验证经度是否正确
     *
     * @param longitude 经度
     * @return true:正确，false:错误
     */
    public static boolean validateLongitude(String longitude) {
        if (StringUtils.isNotEmpty(longitude)) {
            return Pattern.matches(LONGITUDE_MATCH, longitude);
        }
        return false;
    }

    /**
     * 验证纬度是否正确
     *
     * @param latitude 纬度
     * @return true:正确，false:错误
     */
    public static boolean validateLatitude(String latitude) {
        if (StringUtils.isNotEmpty(latitude)) {
            return Pattern.matches(LATITUDE_MATCH, latitude);
        }
        return false;
    }


    /**
     * 验证数字或小数
     *
     * @param str
     * @return true:验证通过，false:验证不通过
     */
    public static boolean isNumber(String str) {
        if (StringUtils.isEmpty(str))
            return false;
        Pattern pattern = Pattern.compile(NUMBER);
        return pattern.matcher(str).matches();
    }

    /**
     * 获取几位随机数据
     *
     * @param count 位数
     * @return
     */
    public static String getRandomStr(int count) {
        String base = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
        Random random = new Random();
        StringBuffer sb = new StringBuffer();

        for (int i = 0; i < count; ++i) {
            int number = random.nextInt(base.length());
            sb.append(base.charAt(number));
        }

        return sb.toString();
    }

    /**
     * 去除字符串中的空格，tab，回车
     *
     * @param str
     * @return
     */
    public static String replaceBlank(String str) {
        String dest = "";
        if (str != null) {
            Pattern p = Pattern.compile("\\s*|\t|\r|\n");
            Matcher m = p.matcher(str);
            dest = m.replaceAll("");
        }
        return dest;
    }

    /**
     * 生成指定范围内的随机数
     *
     * @param min 最小范围数
     * @param max 最大范围数
     * @return 返回最小范围数 - 最大范围数之间的随机数，包含（min,max）
     */
    public static int randomRange(int min, int max) {
        Random random = new Random();
        int s = random.nextInt(max) % (max - min + 1) + min;
        return s;
    }

    /**
     * 获取页数
     *
     * @param count  总条数
     * @param number 每页显示多少条数据
     * @return
     */
    public static int getPages(Integer count, Integer number) {
        Integer remainder = count % number;
        if (remainder > 0) {
            return count / number + 1;
        } else {
            return count / number;
        }
    }

    /**
     * 从字符串中获取出生日期
     *
     * @param stringData
     * @return
     */
    public static String getBirthdayByString(String stringData) {
        String birthdayYear = "";
        String birthdayMonth = "";
        String birthdayDay = "";
        if (StringUtils.isNotBlank(stringData) && StringUtils.contains(stringData, "年")) {
            stringData = stringData.substring(stringData.indexOf("年") - 4, stringData.length());
            birthdayYear = stringData.substring(stringData.indexOf("年") - 4, stringData.indexOf("年"));
        }
        if (StringUtils.isNotBlank(stringData) && StringUtils.contains(stringData, "年") && StringUtils.contains(stringData, "月")) {
            birthdayMonth = RegexUtils.getTextContent(stringData, RegexUtils.BIRTHDAY_MONTH);
        }
        if (StringUtils.isNotBlank(stringData) && StringUtils.contains(stringData, "月") && StringUtils.contains(stringData, "日")) {
            birthdayDay = RegexUtils.getTextContent(stringData, RegexUtils.BIRTHDAY_DAY);
        }
        if (StringUtils.isNotBlank(birthdayYear) && StringUtils.isNotBlank(birthdayMonth) && StringUtils.isNotBlank(birthdayDay)) {
            return birthdayYear + "年" + birthdayMonth + "月" + birthdayDay + "日";
        } else if (StringUtils.isNotBlank(birthdayYear) && StringUtils.isNotBlank(birthdayMonth)) {
            return birthdayYear + "年" + birthdayMonth + "月";
        } else if (StringUtils.isNotBlank(birthdayYear)) {
            return birthdayYear + "年";
        }
        return null;
    }

    //山东省菏泽市立医院

    /**
     * 获取字符串中的省、市、区、县信息
     * 山东省菏泽市立医院
     *
     * @param data
     * @return
     */
    public static String getCityByString(String data) {
        // 省
        String province = "";
        // 市
        String city = "";
        // 区
        String region = "";
        // 县
        String county = "";
        String result = "";
        //
        if (StringUtils.isNotBlank(data)) {
            province = RegexUtils.getTextContent(data, RegexUtils.PROVINCE_REGEX);
            city = RegexUtils.getTextContent(data, RegexUtils.PROVINCE_CITY_REGEX);
            region = RegexUtils.getTextContent(data, RegexUtils.CITY_REGION_REGEX);
            county = RegexUtils.getTextContent(data, RegexUtils.CITY_COUNTY_REGEX);
        }
        if (StringUtils.isBlank(province) && StringUtils.isBlank(city)) {
            city = RegexUtils.getTextContent(data, RegexUtils.CITY_REGEX);
            region = RegexUtils.getTextContent(data, RegexUtils.CITY_REGION_REGEX);
            county = RegexUtils.getTextContent(data, RegexUtils.CITY_COUNTY_REGEX);
        }
        if (StringUtils.isBlank(province) && StringUtils.isBlank(city) && StringUtils.isBlank(region)) {
            region = RegexUtils.getTextContent(data, RegexUtils.REGION_REGEX);
            county = RegexUtils.getTextContent(data, RegexUtils.CITY_COUNTY_REGEX);
        }
        if (StringUtils.isBlank(province) && StringUtils.isBlank(city) && StringUtils.isBlank(region) && StringUtils.isBlank(county)) {
            county = RegexUtils.getTextContent(data, RegexUtils.COUNTY_REGEX);
        }


        if (StringUtils.isNotBlank(province)) {
            result += province + "省";
        }
        if (StringUtils.isNotBlank(city)) {
            result += city + "市";
        }
        if (StringUtils.isNotBlank(region)) {
            result += region + "区";
        }
        if (StringUtils.isNotBlank(county)) {
            result += county + "县";
        }
        return result;
    }


    /**
     * 1  转换成 一
     * 15 转换成 十五
     * 25 转换成 二十五
     *
     * @param num
     * @return
     */
    public static String getNumberToString(String num) {
        // for循环中尽量不要用String +=的方式拼接，可以用StringBuilder
        boolean perviousIsZero = false;
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = 0; i < num.length(); i++) {
            int a = num.charAt(i);
            // 判断当前是否为零
            if (a == 48) {
                perviousIsZero = true;
                continue;
            }

            // 判断数字前一个是否是零且当前数字不为零
            if (perviousIsZero) {
                if (a != 48) {
                    stringBuilder.append("零");
                    perviousIsZero = false;
                } else {
                    // 都是零就跳过
                    continue;
                }
            }

            // 获取数字大写。两位数时，如：15转换结果应该为十五，而不是一十五
            if (i == 0 && a == 49 && num.length() == 2) {
                // 获取数位
                stringBuilder.append(getDigitPlace(num.length() - i));
                continue;
            } else {
                stringBuilder.append(getUpperCase(a));
            }
            // 获取数位
            stringBuilder.append(getDigitPlace(num.length() - i));
        }
        return stringBuilder.toString();
    }

    /**
     * 获取数位
     *
     * @param i
     * @return
     */
    private static String getDigitPlace(int i) {
        switch (i) {
            case 2:
            case 6:
            case 10:
                return "十";
            case 3:
            case 7:
            case 11:
                return "佰";
            case 4:
            case 8:
            case 12:
                return "仟";
            case 5:
            case 13:
                return "万";
            case 9:
                return "亿";
            default:
                return "";
        }
    }

    /**
     * 输出数字的大写
     *
     * @param a
     * @return
     */
    private static String getUpperCase(int a) {
        switch (a) {
            case 49:
                return "一";
            case 50:
                return "二";
            case 51:
                return "三";
            case 52:
                return "四";
            case 53:
                return "五";
            case 54:
                return "六";
            case 55:
                return "七";
            case 56:
                return "八";
            case 57:
                return "九";
            default:
                return "";
        }
    }


    /**
     * 比较两个字符串的相识度
     * 核心算法：用一个二维数组记录每个字符串是否相同，如果相同记为0，不相同记为1，每行每列相同个数累加
     * 则数组最后一个数为不相同的总数，从而判断这两个字符的相识度
     *
     * @param str
     * @param target
     * @return
     */
    public static float getSimilarityRatio(String str, String target) {

        int d[][]; // 矩阵
        int n = str.length();
        int m = target.length();
        int i; // 遍历str的
        int j; // 遍历target的
        char ch1; // str的
        char ch2; // target的
        int temp; // 记录相同字符,在某个矩阵位置值的增量,不是0就是1
        if (n == 0 || m == 0) {
            return 0;
        }
        d = new int[n + 1][m + 1];
        for (i = 0; i <= n; i++) { // 初始化第一列
            d[i][0] = i;
        }

        for (j = 0; j <= m; j++) { // 初始化第一行
            d[0][j] = j;
        }

        for (i = 1; i <= n; i++) { // 遍历str
            ch1 = str.charAt(i - 1);
            // 去匹配target
            for (j = 1; j <= m; j++) {
                ch2 = target.charAt(j - 1);
                if (ch1 == ch2 || ch1 == ch2 + 32 || ch1 + 32 == ch2) {
                    temp = 0;
                } else {
                    temp = 1;
                }
                // 左边+1,上边+1, 左上角+temp取最小
                d[i][j] = Math.min(Math.min(d[i - 1][j] + 1, d[i][j - 1] + 1), d[i - 1][j - 1] + temp);
            }
        }

        return (1 - (float) d[n][m] / Math.max(str.length(), target.length())) * 100F;
    }


    public static void main(String[] args) {
//        String data = "诞生了房市鄄城县人民医院";
//        String data = "诞生了房市临淄区人民医院";
        String data = "淄博市中心医院";
        System.out.println(getCityByString(data));

        String A = "中国人民解放军第四军医大学";
        String B = "第四军医大学";
        System.out.println(getSimilarityRatio(A, B));

        System.out.println(replaceBlank("周 济"));

//        Scanner input = new Scanner(System.in);
//        System.out.println("请输入一串数字");
//        String num = input.nextLine();
//        String stringBuilder = getNumberToString(num);
//
//        System.out.println(stringBuilder);

//        System.out.println(StringUtils.isNumeric("sdafkl123"));
//        System.out.println(StringUtils.isNumeric("2002"));
//        System.out.println(StringUtils.isNumeric("2002年"));
//        System.out.println(StringUtils.containsAny("2002年", "年", "月", "日"));
//        System.out.println(StringUtils.containsAny("2002年1月", "年", "月", "日"));
//        System.out.println(StringUtils.containsAny("2002年1月1日", "年", "月", "日"));


//        System.out.println(handleForeignName("菲立普·希阿雷 Philippe G. Ciarlet"));
//
//        System.out.println(getRandomStr(8));
//
//        isNumber("3.3");
//
//        boolean a = isChineseName("阿卜力孜·乃米图拉", "阿卜力孜·乃米图拉".length());
//        System.out.println(a);
//
//        System.out.println(validateLongitude("11.0903283285252"));
//        System.out.println(validateLatitude("23456324"));
//
//
//        String unicodeStr = "{\"languageStandard\":\"\\u5916\\u6587\"}";
//        System.out.println(jsonUnicodeToUtf8(unicodeStr));
    }

}
